import traceback

import bson
from flask import request, g
from wtforms import Form, fields
from app.db.models.users import User
from app.db.models.balances import Balances
from app.errors import ParameterError


class BaseForm(Form):
    def __init__(self, data=None):
        if data:
            data = data
        else:
            if request.method in ['POST', 'DELETE', 'PUT']:
                data = request.json
            elif request.method == 'GET':
                data = request.args.to_dict()
            else:
                data = ''
        super(BaseForm, self).__init__(data=data)

    def validate_for_api(self):
        valid = super(BaseForm, self).validate()
        if valid:
            pass
        else:
            raise ParameterError(msg=self.errors)
        return self


class UidForm(BaseForm):
    uid = fields.StringField()

    def __init__(self, data=None, user=None):
        self.user = user
        self.balance = None
        super(UidForm, self).__init__(data=data)

    def validate_uid(self, uid):
        if not getattr(self, "user", None):
            if g.entity_type == "user":
                self.user = g.user
            else:
                uid = uid.data
                if not uid:
                    raise ParameterError(msg="后台操作必须选择用户")
                try:
                    uid = bson.ObjectId(uid)
                except bson.errors.BSONError:
                    raise ParameterError(msg="用户选择错误")
                user = User.objects.filter(id=uid).first()
                if not user:
                    raise ParameterError(msg="所选用户不存在")
                self.user = user
        self.uid.data = self.user.id
        self.balance = Balances.objects.filter(uid=self.user.id).first()


class PageForm(BaseForm):
    page = fields.IntegerField(default=1)
    limit = fields.IntegerField(default=10)

    def validate_limit(self, limit):
        if limit.data > 50 or limit.data < 0:
            limit.data = 10

    def validate_page(self, page):
        if page.data < 0:
            page.data = 1


def check_object_id(s0: str) -> bson.ObjectId:
    if not s0:
        raise ValueError("Must has a value.")

    oid = bson.ObjectId(s0)
    return oid
